package org.eiahe.hr.interview.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.common.satoken.utils.LoginHelper;
import org.eiahe.hr.interview.domain.InterviewBehaviorOptions;
import org.eiahe.hr.interview.domain.InterviewBehaviorQuestions;
import org.eiahe.hr.interview.domain.InterviewQuestion;
import org.eiahe.hr.interview.domain.InterviewQuestionBank;
import org.eiahe.hr.interview.domain.vo.InterviewQuestionVO;
import org.eiahe.hr.interview.domain.dto.InterviewQuestionQueryDTO;
import org.eiahe.hr.interview.mapper.InterviewBehaviorQuestionsMapper;
import org.eiahe.hr.interview.mapper.InterviewQuestionMapper;
import org.eiahe.hr.interview.service.InterviewBehaviorOptionsService;
import org.eiahe.hr.interview.service.InterviewQuestionBankService;
import org.eiahe.hr.interview.service.InterviewQuestionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author :zhangnn
 * @className :InterviewQuestionServiceImpl
 * @description: TODO
 * @date 2025-08-13 16:47:03
 */
@Slf4j
@Service
public class InterviewQuestionServiceImpl extends ServiceImpl<InterviewQuestionMapper, InterviewQuestion>
    implements InterviewQuestionService {

    @Autowired
    private InterviewBehaviorQuestionsMapper behaviorQuestionsMapper;
    @Autowired
    private InterviewQuestionBankService bankService;
    @Autowired
    private InterviewBehaviorOptionsService behaviorOptionsService;

    /**
     * 分页
     * @param queryDTO
     * @param pageQuery
     * @return
     */
    @Override
    public TableDataInfo<InterviewQuestionVO> selectQuestionBankPage(InterviewQuestionQueryDTO queryDTO, PageQuery pageQuery) {
        LambdaQueryWrapper<InterviewQuestion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(null != queryDTO.getBankId(), InterviewQuestion::getBankId, queryDTO.getBankId());
        queryWrapper.like(StringUtils.isNotBlank(queryDTO.getQuestionTitle()), InterviewQuestion::getQuestionTitle, queryDTO.getQuestionTitle());
        queryWrapper.eq(null != queryDTO.getQuestionType(), InterviewQuestion::getQuestionType, queryDTO.getQuestionType());
        queryWrapper.eq(null != queryDTO.getDifficulty(), InterviewQuestion::getDifficulty, queryDTO.getDifficulty());

        IPage<InterviewQuestionVO> page = this.baseMapper.selectVoPage(pageQuery.build(), queryWrapper);
        List<InterviewQuestionVO> records = page.getRecords();
        records.forEach(i->{
            InterviewQuestionBank bank = bankService.getById(i.getBankId());
            if(Objects.nonNull(bank)){
                i.setBankId(bank.getId());
                i.setBankName(bank.getBankName());
            }
        });

        return TableDataInfo.build(page);
    }

    /**
     * 详情
     * @param id
     * @return
     */
    @Override
    public InterviewQuestion queryById(Long id) {
        InterviewQuestion interviewQuestion = this.baseMapper.selectById(id);
        InterviewQuestionBank bank = bankService.getById(interviewQuestion.getBankId());
        if (Objects.nonNull(bank)) {
            interviewQuestion.setBankName(bank.getBankName());
        }
        return interviewQuestion;
    }

    /**
     * 新增
     *
     * @param question
     */
    @Override
    public void insertQuestion(InterviewQuestion question) {
        question.setCreateBy(LoginHelper.getUsername());
        question.setTenantId(LoginHelper.getTenantId());
        this.baseMapper.insert(question);
    }

    /**
     * 新增行为分析题目
     * @param question
     */
    @Override
    public void insertBehaviorQuestion(InterviewQuestion question) {
        InterviewBehaviorQuestions behaviorQuestions = question.getBehaviorQuestions();
        behaviorQuestions.setTenantId(LoginHelper.getTenantId());
        int insert = behaviorQuestionsMapper.insert(behaviorQuestions);
        //插入选项
        List<InterviewBehaviorOptions> optionsList = question.getOptionsList();
        for (InterviewBehaviorOptions interviewBehaviorOptions : optionsList) {
            interviewBehaviorOptions.setQuestionId(behaviorQuestions.getId());
            interviewBehaviorOptions.setCreateBy(LoginHelper.getUsername());
            interviewBehaviorOptions.setTenantId(LoginHelper.getTenantId());
            behaviorOptionsService.save(interviewBehaviorOptions);
        }
    }

    /**
     * 修改
     *
     * @param questionBank
     * @return
     */
    @Override
    public boolean updateQuestion(InterviewQuestion questionBank) {
        questionBank.setUpdateBy(LoginHelper.getUsername());
        return this.updateById(questionBank);
    }

    /**
     * 修改行为分析题目
     * @param question
     * @return
     */
    @Override
    public boolean updateBehaviorQuestion(InterviewQuestion question) {
        InterviewBehaviorQuestions behaviorQuestions = question.getBehaviorQuestions();
        behaviorQuestions.setQuestionTitle(behaviorQuestions.getQuestionText());
        behaviorQuestions.setUpdateBy(LoginHelper.getUsername());
        behaviorQuestionsMapper.updateById(behaviorQuestions);
        //修改选项
        List<InterviewBehaviorOptions> optionsList = question.getOptionsList();

        //全部删除questionId下的选项
        List<Long > optionIds = behaviorOptionsService.selectOptions(behaviorQuestions.getId()).stream()
            .map(InterviewBehaviorOptions::getId).collect(Collectors.toList());
        behaviorOptionsService.removeBatchByIds(optionIds);
        for (InterviewBehaviorOptions interviewBehaviorOptions : optionsList) {
            interviewBehaviorOptions.setId(null);
            interviewBehaviorOptions.setQuestionId(behaviorQuestions.getId());
            behaviorOptionsService.save(interviewBehaviorOptions);
        }
        return true;
    }

    /**
     * 删除
     * @param id
     * @return
     */
    @Override
    public boolean deleteQuestion(Long id) {
        return this.removeById(id);
    }

    /**
     * 删除行为分析等线上考题
     * @param id
     * @return
     */
    @Override
    public boolean deleteBehaviorQuestion(Long id) {
         behaviorQuestionsMapper.deleteById(id);
         return true;
    }

    /**
     * 根据职位分类和级别生成面试题目
     *
     * @param bankId  题库分类ID
     * @param level   级别(1-初级, 2-中级, 3-高级)
     * @return 面试题目列表
     */
    public List<InterviewQuestion> generateInterviewQuestions(Long bankId, Integer level) {
        // 查询该职位分类下对应级别的所有题目
        LambdaQueryWrapper<InterviewQuestion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(InterviewQuestion::getBankId, bankId)
            .eq(InterviewQuestion::getLevel, level)
            .eq(InterviewQuestion::getStatus, 1) // 只查询启用状态的题目
            .orderBy(true, true, InterviewQuestion::getDifficulty); // 按难度排序，容易的在前

        List<InterviewQuestion> allQuestions = this.baseMapper.selectList(queryWrapper);

        // 如果题目总数小于10，直接返回所有题目
        if (allQuestions.size() < 10) {
            return allQuestions;
        }
        // 按难度分组
        Map<Integer, List<InterviewQuestion>> questionsByDifficulty = allQuestions.stream()
            .collect(Collectors.groupingBy(InterviewQuestion::getDifficulty));

        List<InterviewQuestion> easyQuestions = questionsByDifficulty.getOrDefault(1, new ArrayList<>());
        List<InterviewQuestion> normalQuestions = questionsByDifficulty.getOrDefault(2, new ArrayList<>());
        List<InterviewQuestion> hardQuestions = questionsByDifficulty.getOrDefault(3, new ArrayList<>());

        // 打乱每个难度等级的题目顺序，增加随机性
        Collections.shuffle(easyQuestions);
        Collections.shuffle(normalQuestions);
        Collections.shuffle(hardQuestions);

        List<InterviewQuestion> selectedQuestions = new ArrayList<>();
        double currentTotalScore = 0.0;
        int questionCount = 0;
        final double TARGET_SCORE = 100.0;
        final int MIN_QUESTIONS = 10;
        final int MAX_QUESTIONS = 15;

        // 按题目类型分组，确保覆盖不同类型
        Set<Integer> selectedQuestionTypes = new HashSet<>();
        // 第一轮：优先选择容易的题目，并尽量覆盖不同题目类型
        selectedQuestions.addAll(selectQuestionsByDifficultyAndType(easyQuestions, selectedQuestionTypes, 6, TARGET_SCORE, currentTotalScore));
        currentTotalScore = selectedQuestions.stream().mapToDouble(q -> q.getQuestionScore() != null ? q.getQuestionScore() : 0).sum();
        questionCount = selectedQuestions.size();

        // 第二轮：选择一般难度的题目
        if (questionCount < MAX_QUESTIONS && currentTotalScore < TARGET_SCORE) {
            List<InterviewQuestion> normalSelected = selectQuestionsByDifficultyAndType(
                normalQuestions, selectedQuestionTypes,
                Math.min(4, MAX_QUESTIONS - questionCount),
                TARGET_SCORE, currentTotalScore);
            selectedQuestions.addAll(normalSelected);
            currentTotalScore = selectedQuestions.stream().mapToDouble(q ->
                q.getQuestionScore() != null ? q.getQuestionScore() : 0).sum();
            questionCount = selectedQuestions.size();
        }

        // 第三轮：选择困难的题目
        if (questionCount < MAX_QUESTIONS && currentTotalScore < TARGET_SCORE) {
            List<InterviewQuestion> hardSelected = selectQuestionsByDifficultyAndType(
                hardQuestions, selectedQuestionTypes,
                Math.min(3, MAX_QUESTIONS - questionCount),
                TARGET_SCORE, currentTotalScore);
            selectedQuestions.addAll(hardSelected);
            currentTotalScore = selectedQuestions.stream().mapToDouble(q ->
                q.getQuestionScore() != null ? q.getQuestionScore() : 0).sum();
            questionCount = selectedQuestions.size();
        }

        // 如果题目数量不足10个，从剩余题目中补充
        if (questionCount < MIN_QUESTIONS) {
            List<InterviewQuestion> finalSelectedQuestions = selectedQuestions;
            List<InterviewQuestion> remainingQuestions = allQuestions.stream()
                .filter(q -> !finalSelectedQuestions.contains(q))
                .collect(Collectors.toList());

            int needMore = MIN_QUESTIONS - questionCount;
            for (int i = 0; i < Math.min(needMore, remainingQuestions.size()); i++) {
                selectedQuestions.add(remainingQuestions.get(i));
            }
        }

        // 如果分数接近100分但题目数量还可以增加，进行微调
        if (questionCount < MAX_QUESTIONS && Math.abs(currentTotalScore - TARGET_SCORE) > 5) {
            selectedQuestions = adjustScoreToTarget(selectedQuestions, allQuestions, TARGET_SCORE, MAX_QUESTIONS);
        }

        return selectedQuestions;
    }

    /**
     * 查询行为分析试题
     * @param id
     * @param bankName
     * @return
     */
    @Override
    public InterviewQuestion queryBehaviorQuestionById(Long id,String bankName) {
        InterviewBehaviorQuestions bq = behaviorQuestionsMapper.selectById(id);
        InterviewQuestion iq = new InterviewQuestion();
        if(Objects.nonNull(bq)){
            iq.setId(bq.getId());
            iq.setBankName(bankName);
            iq.setQuestionTitle(bq.getQuestionText());
            iq.setQuestionContent(bq.getDimension());
            iq.setTags(bq.getDimension());
            iq.setLevel(1);
            iq.setBankId(Long.valueOf(bq.getBankId()));
            iq.setDifficulty(1);

            //获取选项
            List<InterviewBehaviorOptions> optionsList = behaviorOptionsService.selectOptions(id);
            iq.setOptionsList(optionsList);
        }
        return iq;
    }

    /**
     * 根据难度和题目类型选择题目
     */
    private List<InterviewQuestion> selectQuestionsByDifficultyAndType(
        List<InterviewQuestion> questions,
        Set<Integer> selectedTypes,
        int maxCount,
        double targetScore,
        double currentScore) {

        List<InterviewQuestion> selected = new ArrayList<>();

        // 优先选择未覆盖的题目类型
        for (InterviewQuestion question : questions) {
            if (selected.size() >= maxCount) break;
            if (currentScore + (question.getQuestionScore() != null ? question.getQuestionScore() : 0) > targetScore * 1.1) {
                continue; // 跳过会导致总分过高的题目
            }

            Integer questionType = question.getQuestionType();
            if (questionType != null && !selectedTypes.contains(questionType)) {
                selected.add(question);
                selectedTypes.add(questionType);
                currentScore += question.getQuestionScore() != null ? question.getQuestionScore() : 0;
            }
        }

        // 如果还需要更多题目，从剩余题目中选择
        for (InterviewQuestion question : questions) {
            if (selected.size() >= maxCount) break;
            if (selected.contains(question)) continue;
            if (currentScore + (question.getQuestionScore() != null ? question.getQuestionScore() : 0) > targetScore * 1.1) {
                continue;
            }

            selected.add(question);
            currentScore += question.getQuestionScore() != null ? question.getQuestionScore() : 0;
        }

        return selected;
    }

    /**
     * 调整题目分数接近目标分数
     */
    private List<InterviewQuestion> adjustScoreToTarget(
        List<InterviewQuestion> selectedQuestions,
        List<InterviewQuestion> allQuestions,
        double targetScore,
        int maxQuestions) {

        double currentScore = selectedQuestions.stream()
            .mapToDouble(q -> q.getQuestionScore() != null ? q.getQuestionScore() : 0)
            .sum();

        List<InterviewQuestion> result = new ArrayList<>(selectedQuestions);

        // 如果当前分数低于目标分数，尝试替换或添加高分题目
        if (currentScore < targetScore && result.size() < maxQuestions) {
            List<InterviewQuestion> remainingQuestions = allQuestions.stream()
                .filter(q -> !result.contains(q))
                .sorted((q1, q2) -> Double.compare(
                    q2.getQuestionScore() != null ? q2.getQuestionScore() : 0,
                    q1.getQuestionScore() != null ? q1.getQuestionScore() : 0))
                .collect(Collectors.toList());

            for (InterviewQuestion question : remainingQuestions) {
                if (result.size() >= maxQuestions) break;
                double newScore = currentScore + (question.getQuestionScore() != null ? question.getQuestionScore() : 0);
                if (newScore <= targetScore * 1.05) { // 允许5%的误差
                    result.add(question);
                    currentScore = newScore;
                }
            }
        }

        return result;
    }
}
